package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.utils.Constants;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @DubboReference
    private CommentApi commentApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    /**
     * 当前用户发布动态
     *
     * @param movement
     * @param imageContent
     */
    public void movements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //判断用户是否输入文本信息
        if (StringUtils.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.disloveError());
        }
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //将图片存入oss中
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String url = ossTemplate.uploadMovement(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), userId);
            medias.add(url);
        }
        movement.setMedias(medias);
        movement.setUserId(userId);
        //调用mongoDbApi存入数据并存入时间线表
        movementApi.publishMovements(movement);
    }

    /**
     * 查询当前用户id的所有动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findByIdMovements(Long userId, int page, int pagesize) {
        //1.调用mongoApi查询当前用户的所有动态信息
        PageResult pageResult = movementApi.findById(userId, page, pagesize);

        List<Movement> items = (List<Movement>) pageResult.getItems();
        //如果没有数据直接返回pageResult对象
        if (items == null || items.size() <= 0) {
            return pageResult;
        }

        //根据id查询用户详情信息
        UserInfo userInfo = userInfoApi.findById(userId);

        List<MovementsVo> list = new ArrayList<>();

        for (Movement item : items) {
            MovementsVo movementsVo = MovementsVo.init(userInfo, item);
            list.add(movementsVo);
        }

        pageResult.setItems(list);

        return pageResult;
    }

    /**
     * 查询当前用户所有好友动态
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findByFriendMovementAll(int page, int pagesize) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //调用mongoApi接口获取所有好友的动态信息
        List<Movement> movementList = movementApi.findByIdFriendMovementAll(userId, page, pagesize);

        return getPageResult(page,pagesize,movementList);

    }

    /**
     * 查询当前用户推荐好友的所有动态
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findByRecommendM(int page, int pagesize) {
        Long userId = UserHolder.getUserId();
        //- 从redis获取当前用户的推荐PID列表
        String redisValue = redisTemplate.opsForValue().get(Constants.MOVEMENTS_RECOMMEND + userId);

        List<Movement> movementList = Collections.EMPTY_LIST;

        if (StringUtils.isEmpty(redisValue)){
            //- 如果不存在，调用API随机获取10条动态数据
            movementList = movementApi.randomRecommendM(pagesize);
        }else {
            //- 如果存在，调用API根据PID列表查询动态数据
            //- 构造VO对象
            String[] split = redisValue.split(",");
            if ((page - 1) * pagesize < split.length ){
                List<Long> pidList = Arrays.stream(split).skip((page - 1) * pagesize).limit(pagesize)
                        .map(item->Long.valueOf(item))
                        .collect(Collectors.toList());
                //调用Api查询推荐好友的所有动态
                movementList = movementApi.findMovementByPid(pidList);
            }
        }
        return getPageResult(page,pagesize,movementList);
    }

    //获取PageResult对象
    private PageResult getPageResult(int page, int pagesize, List<Movement> movementList) {
        if (CollUtil.isEmpty(movementList)){
            return new PageResult();
        }

        Set<Long> userIds = movementList.stream().map(item -> item.getUserId()).collect(Collectors.toSet());

        Map<Long, UserInfo> map = userInfoApi.findByIds(new UserInfo(), new ArrayList<>(userIds));

        List<MovementsVo> vos = new ArrayList<>();

        for (Movement movement : movementList) {
            UserInfo userInfo = map.get(movement.getUserId());
            if (userInfo != null){
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                //从Redis中判断是否点赞过该评论
                String Key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String likeHashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().get(Key, likeHashKey) != null){
                    vo.setHasLiked(1);
                }
                //从Redis中判断是否喜欢过该评论
                String loveHashKey = Constants.MOVEMENT_LOVE_HASHKEY + movement.getId().toHexString();
                if (redisTemplate.opsForHash().get(Key, loveHashKey) != null){
                    vo.setHasLoved(1);
                }
                vos.add(vo);
            }
        }
        return new PageResult(page,pagesize,0,vos);
    }

    /**
     * 根据动态id获取单条动态
     * @param movementId
     * @return
     */
    public MovementsVo findMovement(String movementId) {
        //调用API获取当前动态id的所有动态
        Movement movement = movementApi.findMovement(movementId);

        if (movement == null){
            return null;
        }
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());

        return MovementsVo.init(userInfo, movement);
    }

    /**
     * 动态-点赞
     * @param movementId
     * @return
     */
    public Integer saveLike(String movementId) {
        //判断是否点赞过该评论
        boolean exists = commentApi.findComment(movementId, CommentType.LIKE,UserHolder.getUserId());

        if (exists){
            throw  new BusinessException(ErrorResult.likeError());
        }
        //调用API获取点赞总数
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());

        Integer countLikes = commentApi.saveComments(comment);
        //4、拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();

        redisTemplate.opsForHash().put(key,hashKey,"1");

        return countLikes;
    }

    /**
     * 动态取消点赞
     * @param movementId
     * @return
     */
    public Integer disLike(String movementId) {
        boolean exists = commentApi.findComment(movementId, CommentType.LIKE, UserHolder.getUserId());

        if (!exists){
            throw  new BusinessException(ErrorResult.disLikeError());
        }

        //调用API获取点赞总数
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(UserHolder.getUserId());

        Integer countLikes = commentApi.delete(comment);

        //删除redis中的点赞标记
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();

        redisTemplate.opsForHash().delete(key,hashKey);

        return countLikes;
    }

    /**
     * 动态-喜欢
     * @param movementId
     * @return
     */
    public Integer saveLove(String movementId) {
        //判断是否喜欢过该评论
        boolean exists = commentApi.findComment(movementId,CommentType.LOVE,UserHolder.getUserId());

        if (exists){
            throw  new BusinessException(ErrorResult.likeError());
        }
        //调用API获取喜欢总数
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());

        Integer countLikes = commentApi.saveComments(comment);
        //4、拼接redis的key，将用户的喜欢状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();

        redisTemplate.opsForHash().put(key,hashKey,"1");

        return countLikes;

    }

    /**
     * 动态-取消喜欢
     * @param movementId
     * @return
     */
    public Integer unlove(String movementId) {
        boolean exists = commentApi.findComment(movementId, CommentType.LOVE, UserHolder.getUserId());

        if (!exists){
            throw  new BusinessException(ErrorResult.disLikeError());
        }

        //调用API获取喜欢总数
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(UserHolder.getUserId());

        Integer countLikes = commentApi.delete(comment);

        //删除redis中的喜欢标记
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();

        redisTemplate.opsForHash().delete(key,hashKey);

        return countLikes;
    }

    /**
     * 谁看过我
     * @return
     */
    public List<VisitorsVo> visitors() {
        //查询访问的时间
        String key = Constants.VISITORS_USER;
        String hashKey = UserHolder.getUserId().toString();
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long data = StringUtils.isEmpty(value)?null:Long.valueOf(value);
        //调用API判断今天看过我的用户
        List<Visitors> list = visitorsApi.lookVisitors(data,UserHolder.getUserId());
        if (CollUtil.isEmpty(list)){
            return new ArrayList<>();
        }
        //提取用户id
        List<Long> ids = list.stream().map(item -> item.getVisitorUserId()).collect(Collectors.toList());
        //调用APi获取用户信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(null, ids);
        List<VisitorsVo> vos = new ArrayList<>();
        for (Visitors visitors : list) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            if (userInfo != null){
                VisitorsVo vo = VisitorsVo.init(userInfo, visitors);
                vos.add(vo);
            }
        }
        return vos;
    }
}
